import { observable, action, useStrict, computed, asMap, toJS } from 'mobx';
import BaseStore from './BaseStore';
import FieldEntity from './FieldEntity';
import DetailEntity from './DetailEntity';
import * as API_REQ from '../apis/form';
import * as Util from '../util/formUtil';
import base from '../util/base';
import { _, FieldUtil, DetailUtil, GlobalUtil, Linkage } from '../util/pcPublic';
import { Upload } from 'weaver-mobile-page';

const initState = {
    dataJson: {},
    layoutSourceInfo: {},
    tableInfo: {},
    browserInfo: {},
    linkageCfg: {},
    propFileCfg: {},
    cellInfo: {},
    codeInfo: {},
    fnaInfo: {},
    hrmInfo: {},
    odocInfo: {},
    existChangeFormData: false,
    existChangeRange: [],
    mainData: observable.map ? observable.map({}) : asMap({}),
    detailMap: observable.map ? observable.map({}) : asMap({}),
}

export class LayoutStore extends BaseStore{
    @observable.ref dataJson;
    layoutSourceInfo;
    tableInfo;
    browserInfo;
    linkageCfg;
    propFileCfg;
    cellInfo;
    codeInfo;
    fnaInfo;
    hrmInfo;
    @observable odocInfo;
    existChangeFormData;
    existChangeRange;
    @observable mainData;
    @observable detailMap;
    //附件拖拽路由
    @observable uploadSoteRoute = [];

    @computed get containSignInput(){   //表单是否包含签字意见输入框
        return _.has(this.cellInfo, ["fieldCellInfo", "-4"]) && _.has(this.tableInfo, ["main", "fieldinfomap", "-4", "viewattr"])
            && _.get(this.tableInfo, ["main", "fieldinfomap", "-4", "viewattr"]) >= 1;
    }
    @computed get fieldAttrMap(){
        let attrMap = observable.map ? observable.map({}) : asMap({});
        !_.isEmpty(this.tableInfo) && _.forIn(this.tableInfo, (v,k) =>{
            v.fieldinfomap && _.forIn(v.fieldinfomap, (attr, fieldid) =>{
                attr["tableMark"] = k;
                attr["isDetail"] = k.indexOf("detail_") > -1;
                attr["tableName"] = v.tablename;
                attrMap.set(fieldid.toString(), attr);
            });
        });
        return attrMap;
    }
    @computed get fieldNameMap(){
        let nameMap = observable.map ? observable.map({}) : asMap({});
        !_.isEmpty(this.tableInfo) && _.forIn(this.tableInfo, (v,k) =>{
            v.fieldinfomap && _.forIn(v.fieldinfomap, (attr, fieldid) =>{
                if(!!attr.fieldname)
                    nameMap.set(`${k}.${attr.fieldname.toUpperCase()}`, fieldid);
            });
        });
        return nameMap;
    }
    @computed get fieldCellMap(){
        let cellMap = {};
        _.forIn(this.dataJson.etables, (v,k) =>{
            v.ec.forEach(cellObj =>{
                if(cellObj.etype == "3")
                    cellMap[cellObj.field] = cellObj;
            });
        });
        return cellMap;
    }
    @computed get rowSubPanelMap(){
        let rowMap = {};
        const subPanelInfo = this.cellInfo.subPanelInfo || {};
        _.forIn(subPanelInfo, (v,k) =>{
            rowMap[`${v.symbol}_${v.rowid}`] = k;
        });
        return rowMap;
    }

    constructor(){
        super();
        this.resetState();
    }
    @action
    setUploadSoteRoute = (pathname = "/req" , fieldMark) => {
        let stores = new Upload.Store({route:pathname, id:fieldMark+"_uploadadjustment", editNameId:"resetname"});
        stores.initLayout(pathname );
        this.uploadSoteRoute.push({key: fieldMark, store: stores});
    }


    @action('初始化布局')
    doInitLayout = (data) =>{
        const { isSourceLayout ,setTabKey} = base.wfGlobalStore;
        //样式信息，必须render模板前append到body，否则IE下保存后跳转异常
        if(!_.isEmpty(data.propFileCfg))
            GlobalUtil.imageStyleHander(data.propFileCfg);
        if(!isSourceLayout && !_.isEmpty(data.cellInfo))
            window.jQuery("body").append(data.cellInfo.style.layoutStyle).append(data.cellInfo.style.scriptStyle);
        this.tableInfo = data.tableInfo;
        this.browserInfo = data.browserInfo;
        this.linkageCfg = data.linkageCfg;
        this.propFileCfg = data.propFileCfg;
        this.cellInfo = data.cellInfo;
        this.codeInfo = data.codeInfo;
        this.fnaInfo = data.fnaInfo || {};
        this.hrmInfo = data.hrmInfo || {};
        this.odocInfo = data.odocInfo || {};
        // 跳转到正文tab
        if(data.odocInfo && data.odocInfo.mobileInfo && data.odocInfo.mobileInfo.isShowDocTab && data.odocInfo.mobileInfo.opentextdefaultnode){
            const {tabKey}=base.wfGlobalStore;
            const nowTabKey = tabKey;
            setTabKey("odoc"); 
            Util.tabChangTriggerEvent("odoc",nowTabKey);
        }
        data.maindata && _.forIn(data.maindata, (v,k) =>{
            const fieldid = k.substring(5);
            const { commonParam } = base.wfGlobalStore;
            if(this.fieldAttrMap.has(fieldid) && commonParam.isviewonly == 1){
                const fieldAttr = this.fieldAttrMap.get(fieldid);
                if(fieldAttr.htmltype === 2 && fieldAttr.detailtype === 2)
                    v.value = GlobalUtil.manageCssFilePollute(v.value, `field${fieldid}_swapDiv`);
            }
            this.mainData.set(k, new FieldEntity(k, v));
        });
        data.tableInfo && _.forIn(data.tableInfo, (v,k) =>{
            if(k.indexOf("detail_") > -1)
                this.detailMap.set(k, new DetailEntity(v.detailtableattr, v.fieldinfomap));
        });
        //最后一步渲染布局信息
        if(isSourceLayout){     //E7源码html模板
            this.doInitSourceLayout(data.layoutSourceInfo);
        }else{
            this.dataJson = data.datajson && data.datajson.eformdesign;
        }
        //加载明细数据
        this.loadDetailData();
    }

    @action('初始化源码源码')
    doInitSourceLayout = (layoutSourceInfo) =>{
        if(_.isEmpty(layoutSourceInfo))
            return;
        const { datajson,styleStr,cssFiles,fieldCellInfo,nodeMarkContent } = layoutSourceInfo;
        window.jQuery("body").append(styleStr||"");
        GlobalUtil.loadCssFileContent(cssFiles, "excelTempDiv");
        delete layoutSourceInfo.datajson;
        this.layoutSourceInfo = layoutSourceInfo;
        this.cellInfo.fieldCellInfo = fieldCellInfo;
        this.cellInfo.nodeMarkContent = nodeMarkContent;
        this.dataJson = datajson;       //最后渲染布局
    }

    @action('加载明细数据')
    loadDetailData = () =>{
        const { isSourceLayout } = base.wfGlobalStore;
        let detailmark = "";
        this.detailMap.forEach((detailObj,key) =>{
            if(_.has(this.cellInfo, ["subPanelInfo", key]) || isSourceLayout)
                detailmark += key+",";
        });
        if(detailmark !== "")
            detailmark = detailmark.substring(0, detailmark.length-1);
        const { commonParam,urlParams,commonApiParam } = base.wfGlobalStore;
        if(detailmark !== "") {
            const apiParams = {...urlParams};
            if(commonParam.iscreate != "1")
                apiParams["requestid"] = commonParam.requestid;
            apiParams["detailmark"] = detailmark;
            apiParams["reqParams"] = JSON.stringify(commonApiParam);
            API_REQ.loadDetailData(apiParams).then((data)=>{
                if(typeof data !== "object" || _.isEmpty(data)){
                    //明细数据接口异常阻断
                    alert("加载明细数据发生异常，请联系管理员");
                    return;
                }
                _.forIn(data, (v,detailMark) =>{
                    if(this.detailMap.has(detailMark)){
                        const detailObj = this.detailMap.get(detailMark);
                        detailObj.initDetailData(v);
                    }
                });
                //延时加载，非当前页字段转换信息(浏览按钮转name)
                if("delayCacheKey" in data && !!data.delayCacheKey){
                    const delayApiParams = {...apiParams, ...{isDelayConvertName:"1", delayCacheKey: data.delayCacheKey}};
                    API_REQ.loadDetailData(delayApiParams).then(delaydatas =>{
                        _.forIn(delaydatas.datas, (v,detailMark) =>{
                            const detailObj = this.detailMap.get(detailMark);
                            const { detailData } = detailObj;
                            _.forIn(v, (valueObj,fieldMark) =>{
                                if(detailData.has(fieldMark)){
                                    const fieldObj = detailData.get(fieldMark);
                                    if(fieldObj.value === valueObj.value){      //延时请求过程中此字段值没变过才改变
                                        fieldObj.changeValueObj(valueObj);
                                    }
                                }
                            });
                        });
                    });
                }
                //页面加载触发联动应在默认新增明细前，新增加的行联动在添加时会自动触发
                this.triggerAllLinkage(2);
                //节点操作者-默认新增空明细
                if(parseInt(commonParam.isviewonly || 0) !== 1){
                    detailmark.split(",").map(detailMark =>{
                        const detailObj = this.detailMap.get(detailMark);
                        const { attr,indexnum } = detailObj;
                        const { isdefault,isadd,defaultrows } = attr;
                        if(indexnum === 0 && isdefault === 1){     //无数据情况触发默认新增空明细
                            for(let i=0; i<parseInt(defaultrows); i++){
                                DetailUtil.addRow(detailMark);
                            }
                        }
                    });
                }
                //加载代码块,触发代码块内ready等事件
                Util.loadScript();
            });
        }else {
            this.triggerAllLinkage(2);
            Util.loadScript();
        }
    }

    @action('字段值不存在时需初始化字段值对象')
    initFieldObj = (tableMark, fieldMark) =>{
        let dataObj = null;
        if(tableMark.indexOf("detail") === -1)
            dataObj = this.mainData;
        else
            dataObj = this.detailMap.get(tableMark).detailData;
        if(dataObj && !dataObj.has(fieldMark)){
            dataObj.set(fieldMark, new FieldEntity(fieldMark));
        }
        return dataObj.get(fieldMark);
    }

    @action('修改单个字段值信息')
    changeSingleFieldValue = (fieldMark, valueInfo={}, variableInfo={}) =>{
        const changeDatas = {};
        if(!_.isEmpty(valueInfo))
            changeDatas[fieldMark] = valueInfo;
        const fieldVars = {};
        if(!_.isEmpty(variableInfo))
            fieldVars[fieldMark] = variableInfo;
        this.changeMoreFieldData(changeDatas, fieldVars);
    }

    @action('修改字段值的唯一入口，统一此处做字段值变更的联动总控')
    changeMoreFieldData = (changeDatas={}, fieldVars={}) =>{
        let fieldKeys = Object.keys(changeDatas);
        Object.keys(fieldVars).map(fieldMark =>{
            if(_.indexOf(fieldKeys,fieldMark) === -1)
                fieldKeys.push(fieldMark);
        });
        let changeMap = {};
        fieldKeys.map(fieldMark =>{
            const fieldAttr = FieldUtil.getFieldAttr(fieldMark, this.fieldAttrMap);
            if(!fieldAttr)
                return true;
            if(fieldMark.indexOf("_") > -1 && parseInt(fieldMark.substring(fieldMark.indexOf("_")+1)) < 0)
                return true;    //明细字段非法格式
            const tableMark = fieldAttr.tableMark;
            this.initFieldObj(tableMark, fieldMark);    //需先初始化
            const fieldObj = FieldUtil.getFieldObj(fieldMark, tableMark, this.mainData, this.detailMap);
            if(fieldMark in changeDatas){
                const valueObj = changeDatas[fieldMark];
                let oldValue = fieldObj.value;
                let newValue = Util.convertNull(valueObj.value);
                newValue = FieldUtil.convertValueBeforeChangeStore(newValue, fieldAttr);
                fieldObj.changeValueObj({...valueObj, ...{value:newValue}});   //修改字段值信息
                //对比修改前值判断字段值是否变化
                if(fieldAttr.htmltype === 1 && fieldAttr.detailtype != 1){
                    oldValue = oldValue.toString();
                    newValue = newValue.toString();
                }
                const existChange = !(typeof oldValue === typeof newValue && oldValue == newValue);    //类型一致且两等号判断
                changeMap[fieldMark] = {existChange, newValue};
            }
            if(fieldMark in fieldVars){
                const varObj = fieldVars[fieldMark] || {};
                //联动变更字段类型，重新初始化store
                if("changeFieldType" in varObj){
                    const isCardEdit = tableMark.indexOf("detail_") > -1 ? DetailUtil.judgeIsCardEdit(this.detailMap.get(tableMark)) : false;
                    fieldObj.initFieldStore(fieldMark, varObj["changeFieldType"], isCardEdit);
                }
                fieldObj.changeVariable(varObj);
            }
        });
        //修改字段值完成后触发字段值变更联动
        _.forIn(changeMap, (obj,fieldMark) =>{
            if(obj.existChange === true){
                this.existChangeFormData = true;    //表单字段值修改过，用于关闭时提示信息判断
                this.existChangeRange.push(fieldMark);
                const isDetail = fieldMark.indexOf("_") > -1;
                const fieldid = isDetail ? fieldMark.substring(5, fieldMark.indexOf("_")) : fieldMark.substring(5);
                const rowIndex = isDetail ? fieldMark.substring(fieldMark.indexOf("_")+1) : "-1";
                let tableMark = "";
                if(this.fieldAttrMap.has(fieldid))
                    tableMark = this.fieldAttrMap.get(fieldid).tableMark;
                this.triggerAllLinkage(1, tableMark, fieldid, rowIndex);
                //最后触发开发代码绑定的监听函数
                window.WfForm.triggerFieldBindEvent(fieldMark, obj.newValue);
            }
        })
    }

    @action('触发联动总控')
    //triType（1：字段值变化触发  2：页面加载触发  3：新增行触发  4、删除行触发）
    triggerAllLinkage = (triType, tableMark, triFieldid, rowIndex) =>{
        const {variableMap} = base.wfGlobalStore;
        let startTime = new Date().getTime()
        const fun = () =>{
            let caculate_Complete = variableMap.get("caculate_Complete")||false;
            let interval = new Date().getTime() - startTime;
            if(!caculate_Complete && interval<3000){
                setTimeout(()=>{
                    fun()
                },200)
            }else{
                new Linkage(triType).doTrigger(tableMark, triFieldid, rowIndex);
            }
        }
        fun();
    }

    @action('改变公文参数')
    setOdocInfo = (obj={}) =>{
        this.odocInfo = obj;
    }

    @action('重置状态')
    resetState = () =>{
        this.changeState(initState);
        this.resetVariableMap();
    }

}